package com.hxb.burp.handlers;

import burp.api.montoya.MontoyaApi;
import burp.api.montoya.http.handler.*;
import burp.api.montoya.http.message.requests.HttpRequest;
import burp.api.montoya.http.message.responses.HttpResponse;
import burp.api.montoya.logging.Logging;
import com.hxb.burp.utils.AjaxResult;
import com.hxb.burp.utils.HttpUtils;
import com.hxb.burp.utils.IniUtils;
import mjson.Json;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * burp_extendsion2
 *
 * @author 黄小斌
 * @date 2023-10-27
 */
public class WxAppletHandler implements HttpHandler {
    private MontoyaApi api = null;
    private Logging logger = null;

    private static final String ENCODE = "utf-8";

    private String lastData = "";

    private final ExecutorService threadPool = Executors.newScheduledThreadPool(5);

    public WxAppletHandler(MontoyaApi api) {
        this.api = api;
        this.logger = api.logging();
        api.userInterface().registerSuiteTab("微信小游戏数据助手", jPanel());
    }

    public WxAppletHandler() {

    }


    JTextField serverUrl;
    JTextArea consoleArea;

    JCheckBox autoSend, showAll;
    JScrollPane center;

    private static final String DEFAULT_URL = "http://localhost:9999/";
    private static final String SECTION = "applet";

    private void initValues() {
        serverUrl.setText(IniUtils.getProperties(SECTION, "serverUrl", DEFAULT_URL));
        autoSend.setSelected("true".equals(IniUtils.getProperties(SECTION, "autoSend", "true")));
        showAll.setSelected("true".equals(IniUtils.getProperties(SECTION, "showAll", "false")));
    }

    JPanel mainPlane;

    private JPanel jPanel() {
        int width = 1900;//
//        int width = 1900 - 60;
        mainPlane = new JPanel();
        mainPlane.setLayout(null);
        JLabel jLabel = new JLabel("服务器地址：");
        jLabel.setBounds(5, 5, 85, 25);
        serverUrl = new JTextField(DEFAULT_URL);
        serverUrl.setBounds(95, 5, 420, 25);
        JButton testButton = getTestButton();
        autoSend = new JCheckBox("发送请求");
        autoSend.setBounds(620, 5, 90, 25);

        showAll = new JCheckBox("显示所有请求");
        showAll.setToolTipText("显示所有请求");
        showAll.setBounds(720, 5, 100, 25);

        JButton clearButton = getCleanButton();
        JButton sendOnceMore = getSendOnceButton();
        JButton saveButton = getSaveButton();

        consoleArea = new JTextArea("");
        consoleArea.setEditable(false);
        center = new JScrollPane(consoleArea);
        center.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        center.setAutoscrolls(false);
        center.setBounds(50, 70, width, 300);


        mainPlane.add(jLabel);
        mainPlane.add(serverUrl);
        mainPlane.add(saveButton);
        mainPlane.add(autoSend);
        mainPlane.add(showAll);
        mainPlane.add(clearButton);
        mainPlane.add(testButton);
        mainPlane.add(sendOnceMore);
        mainPlane.add(center);
        this.initValues();
        this.initListener();
        return mainPlane;
    }

    private JButton getCleanButton() {
        JButton clearButton = new JButton("清空日志");
        clearButton.setBounds(830, 5, 90, 25);

        clearButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                consoleArea.setText("");
            }
        });
        return clearButton;
    }

    private JButton getTestButton() {
        JButton testButton = new JButton("测试链接");
        testButton.setBounds(525, 5, 90, 25);
        testButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    Json json = Json.object();
                    json.set("code", 0);
                    json.set("msg", "测试的 Msg");
                    printConsole("发送测试数据: " + json.toString());
                    sendHttpMessageNow(json.toString());
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }
        });
        return testButton;
    }

    private JButton getSaveButton() {
        JButton jButton = new JButton("保存配置");
        jButton.setBounds(1020, 5, 90, 25);

        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                List<IniUtils.IniConfig> list = new ArrayList<>();
                list.add(new IniUtils.IniConfig("serverUrl", serverUrl.getText()));
                list.add(new IniUtils.IniConfig("autoSend", autoSend.isSelected()));
                list.add(new IniUtils.IniConfig("showAll", showAll.isSelected()));
                IniUtils.addPropertiesList(SECTION, list);
                printConsole("配置保存成功！");
            }
        });
        return jButton;
    }

    private void initListener() {
        if (api != null) {
            int width = this.api.userInterface().swingUtils().suiteFrame().getComponent(0).getWidth() - 10;
            int height = this.api.userInterface().swingUtils().suiteFrame().getComponent(0).getHeight() - 120;
            center.setBounds(5, 35, width, height);
            api.userInterface().swingUtils().suiteFrame().addComponentListener(new ComponentListener() {
                @Override
                public void componentResized(ComponentEvent e) {
                    int width = mainPlane.getWidth() - 10;
                    int height = mainPlane.getHeight() - 40;
//                    center.setBounds(20, 55, api.userInterface().swingUtils().suiteFrame().getWidth() - 60, 300);
                    center.setBounds(5, 35, width, height);
                }

                @Override
                public void componentMoved(ComponentEvent e) {

                }

                @Override
                public void componentShown(ComponentEvent e) {

                }

                @Override
                public void componentHidden(ComponentEvent e) {

                }
            });
        }
    }

    private JButton getSendOnceButton() {
        JButton sendOnceMore = new JButton("再次发送");
        sendOnceMore.setBounds(925, 5, 90, 25);
        sendOnceMore.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    if (lastData == null || lastData.isEmpty()) {
                        printConsole("最后一次请求数据为空，跳过！");
                        return;
                    }
                    printConsole("SendData：" + lastData);
                    sendHttpMessage(lastData);
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }
        });
        return sendOnceMore;
    }

//    public static void main(String[] args) {
//        Extension x = new Extension();
//        JFrame jFrame = new JFrame("title");
//        jFrame.setPreferredSize(new Dimension(1600, 500));
//        jFrame.getContentPane().setLayout(null);//设置边框布局
//        JPanel xd = x.jPanel();
//        xd.setBounds(10, 10, 1500, 500);
//        jFrame.add(xd);
//        jFrame.pack();
//        jFrame.setVisible(true);
//    }


    public static void main(String[] args) {
        WxAppletHandler handler = new WxAppletHandler();
        JPanel def = handler.jPanel();

        JFrame jFrame = new JFrame("xxxx");
        jFrame.setSize(1000, 500);
        jFrame.add(def);
        jFrame.addComponentListener(new ComponentListener() {
            @Override
            public void componentResized(ComponentEvent e) {
                handler.center.setBounds(5, 35, def.getWidth() - 10, def.getHeight() - 40);
            }

            @Override
            public void componentMoved(ComponentEvent e) {

            }

            @Override
            public void componentShown(ComponentEvent e) {

            }

            @Override
            public void componentHidden(ComponentEvent e) {

            }
        });
        jFrame.setVisible(true);
    }

    @Override
    public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) {
        return RequestToBeSentAction.continueWith(requestToBeSent);
    }

    @Override
    public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) {
        HttpRequest request = responseReceived.initiatingRequest();
        try {
            String responseBody = new String(((HttpResponse) responseReceived).body().getBytes(), ENCODE);
            Json body = Json.read(responseBody);
            String requestUrl = request.url();
            if (showAll.isSelected()) {
                if (requestUrl.contains("game.weixin.qq.com")) {
                    logger.logToOutput(requestUrl);
                    printConsole("Request Url:" + requestUrl);
                    printConsole("Request Message:" + new String(request.body().getBytes(), ENCODE));
                    printConsole("Request Response:" + responseBody);
                }
            }

            if (request.url().contains("/cgi-bin/gameweappauthwap/login")) {
                this.logger.logToOutput("QueryUrl ：" + request.url());
                try {
                    Json json = Json.object();
                    request.headers().forEach(item -> {
                        if ("Referer".equals(item.name())) {
                            String value = item.value().replaceAll("(.*)(wx\\w+)(.*)", "$2");
                            json.set("appId", value);
                        }
                    });
                    json.set("session", body.at("data").at("session_id").getValue());
                    json.set("nickName", body.at("data").at("nick_name").getValue());
                    json.set("headImgUrl", body.at("data").at("head_img_url").getValue());

                    this.logger.logToOutput(json.toString());
                    printConsole(json.toString());
                    this.sendHttpMessage(json.toString());
                } catch (Exception e) {
                    this.logger.logToOutput(e.getMessage());
                }
            }
        } catch (Exception e) {
            this.logger.logToOutput(e.getMessage());
        }
        return ResponseReceivedAction.continueWith(responseReceived);
    }

    private void printConsole(String messge) {
        consoleArea.append(messge + "\n");
    }


    private void sendHttpMessage(String message) throws IOException {
        if (!autoSend.isSelected()) {
            return;
        }
        sendHttpMessageNow(message);
    }

    private void sendHttpMessageNow(String message) throws IOException {
        lastData = message;
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                String urlStr = serverUrl.getText();
                printConsole("发送数据：[url=" + urlStr + "],[data=" + message + "]");
                AjaxResult result = HttpUtils.sendPost(urlStr, message);
                if (result.isSuccess()) {
                    printConsole("请求结果：" + result.getData().toString());
                } else {
                    printConsole("请求异常: " + result.getMsg());
                }
            }
        });
    }
}
